package roboGP;

import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;

import robocode.BattleResults;
import robocode.control.BattleSpecification;
import robocode.control.RobotSpecification;

public class BattleRunnerMaster extends BattleRunner 
{
	private static int THREADS = 2;
	private BattleRunnerSlave[] _arenas;

	public BattleRunnerMaster()
	{
		super();
		for (int i = 0; i < THREADS - 1; i++)
		{
			try {
				_arenas[i] = (BattleRunnerSlave) Naming.lookup("//localhost/BattleRunnerSlave" + i);
			} 
			catch (MalformedURLException | RemoteException | NotBoundException e) 
			{
				e.printStackTrace();
				System.exit(0);
			}
		}
	}

	/**
	 * Per ogni Metarobot avvia la battaglia contro tutti i robot avversari, raccogliendo i risultati e
	 * calcolando pe ciascun Metarobot la propria funzione di fitness.
	 * 
	 * @param metaRobots Una lista contenente i Metarobot.
	 * @param adverSet Una lista contenente gli avversari.
	 * @param samples Lista dei nomi dei robot avversari.
	 * @param rounds Numero di round di ogni battaglia.
	 * @throws IllegalArgumentException Se il numero di avversari non è multiplo del numero di thread.
	 */
	public void runBatchWithSAversaries(MetaRobot metaRobots[], String adverSet[], double[] weight, int rounds)
	{		
		if (adverSet.length % THREADS != 0)
		{
			throw new IllegalArgumentException();
		}

		for (int i = 0; i < metaRobots.length; i++) 
		{
			int robotScore[] = new int[adverSet.length];
			int totalScore[] = new int[adverSet.length];

			int j = 0;
			try 
			{
				while (j < adverSet.length/THREADS)
				{

					for (int k = j; k < j + THREADS; k++)
					{
						String metaBot = EvolutionChamber.PACKAGE+"."+metaRobots[i].getName()+"*";

						if (k == 0)
						{
							String opponent = adverSet[j];
							RobotSpecification[] selectedBots = engine.getLocalRepository(metaBot+", "+opponent);
							BattleSpecification battleSpec = new BattleSpecification(rounds, battlefield, selectedBots);
							engine.runBattle(battleSpec, true);
						}
						else
						{
							String opponent = adverSet[j+k];
							RobotSpecification[] selectedBots = engine.getLocalRepository(metaBot+", "+opponent);
							_arenas[k-1].runBattle(selectedBots, rounds);
						}
					}

					for (int k = 0; k < THREADS; k++)
					{
						BattleResults[] results = null;
						if (k == 0)
						{
							results = battleObserver.getResults();
						}
						else
						{
							results = _arenas[k-1].getResults();
						}
						System.out.println("\nBATTLE: "+ results[0].getTeamLeaderName() +" vs " 
								+ results[1].getTeamLeaderName());
						System.out.println("SCORE: " + results[0].getTeamLeaderName() +" --> " + results[0].getScore());
						System.out.println("SCORE: " + results[1].getTeamLeaderName() +" --> " + results[1].getScore());

						robotScore[j+k] = results[0].getScore();
						totalScore[j+k] = results[0].getScore() + results[1].getScore();
					}

					j = j + THREADS;

				}	
			} 
			catch (RemoteException e) 
			{
				e.printStackTrace();
			}
			EvolutionChamber.metaRobots[i].setFitness(computeFitness(robotScore, totalScore, weight));
		}
	}

}
